const state = {
    // 数据列索引 (持久化)
    colIndexes: {},// col : values
    // 筛选条件
    filters: {},// name:value

    styles: {},
    data: {},//id : row (持久化)
    // 筛选结果
    resultIds: [], // ids

    //级联筛选条件
    cascadeColMeta: {
        'catalog': ['大类', '中类', '小类'],
    },
    // 级联列数据关系 key:本级数据,value:下一级数据列表 (持久化)
    cascadeData: {},
    // 级联选择的筛选条件 name:value
    cascadeFilters: {},

    resetFlag: 0,
};

const getters = {
    colNames(state) {
        return Object.keys(state.colIndexes).filter(key => key !== '__id');
    },
    getFilters(state) {
        return Object.values(state.filters);
    },
    results(state) {
        return state.resultIds.map(id => {
            let d = Object.assign({}, state.data[id]);
            delete d.__id;
            return d;
        });
    },
    /**
     * 获取级联数据，param:{catalog:级联分类key,value:想要获取的数据key}
     * @param state
     * @returns {Function} param.value对应的下一级数据列表，失败返回空列表
     */
    getCascadeValues: (state) => (param) => {
        // let parentColName = null;

        let names = state.cascadeColMeta[param.catalog];
        if (!names) {
            return [];
        }
        let data = state.cascadeData[param.catalog];
        if (data) {
            return data[param.value];
        }
        return [];
        // let index = names.findIndex(n => n === param.name);
        // if (index > 0) {
        //     parentColName = names[index - 1];
        // }
        // if (parentColName !== null) {
        //     return state.cascadeData[param.parentValue];
        // }
        // return [];
    },
};

const _isEmptyString = function (val) {
    return (typeof val) === 'string' && val.trim().length <= 0;
};

const _fillCascadeData = function (state, line) {
    Object.keys(state.cascadeColMeta).forEach(metaKey => {
        let meta = state.cascadeColMeta[metaKey];

        let filterLine = meta.map(rowName => {
            let rowValue = line[rowName];
            if (rowValue && !_isEmptyString(rowValue)) {
                return rowValue;
            }
            return null;
        });
        for (let i = 1; i < meta.length; i++) {
            let element = filterLine[i];
            if (!element) {
                continue;
            }
            let parentElement = filterLine[i - 1];
            if (!parentElement) {
                continue;
            }
            let baseNode = state.cascadeData[metaKey];
            if (!baseNode) {
                baseNode = {};
                state.cascadeData[metaKey] = baseNode;
            }

            let array = baseNode[parentElement];
            if (!array) {
                array = [];
                baseNode[parentElement] = array;
            }
            let parentNodeSet = new Set(array).add(element);
            baseNode[parentElement] = Array.from(parentNodeSet);
        }
    });
};

const mutations = {
    reset(state, data) {
        state.colIndexes = {};
        state.filters = {};
        state.styles = {};
        state.data = {};
        state.resultIds = [];
        state.cascadeData = {};
        state.cascadeFilters = {};

        state.resetFlag = state.resetFlag + 1;
        let index = 1;
        let colIndexes = {};
        Object.values(data).forEach(d => {
            d.__id = index++;
            state.data[d.__id] = d;
            Object.keys(d).forEach(key => {
                let val = d[key];
                if (!val) {
                    return;
                }
                if (_isEmptyString(val)) {
                    return;
                }
                // cascade
                _fillCascadeData(state, d);
                // index
                let indexes = colIndexes[key];
                if (!indexes) {
                    indexes = new Set();
                    colIndexes[key] = indexes;
                }
                indexes.add(val);
            });
        });

        // eslint-disable-next-line no-console
        // console.log(colIndexes);
        Object.keys(colIndexes).forEach(k => {
            state.colIndexes[k] = Array.from(colIndexes[k]);
        });
        // eslint-disable-next-line no-console
        // console.log('=====');
        // eslint-disable-next-line no-console
        // console.log(state.colIndexes);

        state.data = Object.assign({}, state.data);
        state.colIndexes = Object.assign({}, state.colIndexes);

        // state.resetFlag = false;
        // eslint-disable-next-line no-console
        // console.log(state.cascadeData)
    },
    doFilterData(state) {
        let result = [];
        Object.keys(state.data).forEach(id => {
            let obj = state.data[id];
            let pass = true;
            Object.values(state.filters).forEach(f => {
                if (f.value === null) {
                    return;
                }
                let val = obj[f.name];
                if (f.value !== val) {
                    pass = false;
                }
            });
            Object.values(state.cascadeFilters).forEach(f => {
                if (f.value === null) {
                    return;
                }
                let val = obj[f.name];
                if (f.value !== val) {
                    pass = false;
                }
            });
            if (pass) {
                result.push(id);
            }
        });
        state.resultIds = Object.assign(result);
    },
    addFilter(state, filter) {
        state.filters[filter.name] = filter;
        state.filters = Object.assign({}, state.filters);
    },
    addFilters(state, filters) {
        filters.forEach(filter => {
            state.filters[filter.name] = filter;
        });
        state.filters = Object.assign({}, state.filters);
    },
    removeFilter(state, filterName) {
        delete state.filters[filterName];
        state.filters = Object.assign({}, state.filters);
    },
    setCascadeFilters(state, filters) {
        filters.forEach(filter => {
            state.cascadeFilters[filter.name] = filter;
        });
        state.cascadeFilters = Object.assign({}, state.cascadeFilters);
    }
};

const actions = {
    addFilter({commit}, filter) {
        return commit('addFilter', filter);
    },
    addFilters({commit}, filters) {
        return commit('addFilters', filters);
    },
    removeFilter({commit}, filterName) {
        return commit('removeFilter', filterName);
    },
    reset({commit}, data) {
        return commit('reset', data);
    }
};

export default {
    state,
    getters,
    mutations,
    actions
}